﻿using Huioo.Learning.CSharp.Abstractions;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Huioo.Learning.Csharp.ConcurrencyAndAsynchronous
{
    public class TaskRunUsing : ModelUsing
    {
        //private readonly int _millisecendsDelay;
        //private CancellationTokenSource? _cts;

        //public TaskRunUsing(int x=1000)
        //{
        //    _millisecendsDelay = x;
        //}

        public override void Run()
        {
            using (var cts = new CancellationTokenSource())
            {
                int id = 0;
                AddLog($"[{id}] RunTask cts.IsCancellationRequested = {cts.IsCancellationRequested}");
                cts.Cancel();
                RunTask(101, cts.Token); // 异步任务，异常不会传递到当前线程。
                AddLog($"[{id}] RunTask cts.IsCancellationRequested = {cts.IsCancellationRequested}");
            }

            using (var cts = new CancellationTokenSource())
            {
                RunTaskAndWait(50, cts.Token); // 无异常

                cts.Cancel(); //取消Token。调用Task.Run()时，传参Token，任务不启动。
                RunTaskAndWait(60, cts.Token); // 有异常，Task.Wait()抛出异常
            }

            using (var cts = new CancellationTokenSource(1000))
            {
                // 1s后，Token自动取消
                int id = 100;
                var task = Task.Run(() =>
                {
                    AddLog($"[{id}] begin");
                    Thread.Sleep(3000);
                    AddLog($"[{id}] end");
                }, cts.Token);
                try
                {
                    //task.Wait(); //无异常。异步任务正常执行结束。
                    task.Wait(cts.Token); //有异常。Token中途取消。异步任务正常执行结束。
                }
                catch (Exception ex)
                {
                    AddLog($"[{id}] {ex.Message}");
                }
            }

            using (var cts = new CancellationTokenSource(1000))
            {
                // 1s后，Token自动取消
                int id = 101;
                var task = Task.Run(async () =>
                {
                    AddLog($"[{id}] begin");
                    //await Task.Delay(3000); //无影响
                    await Task.Delay(3000, cts.Token);//提前终止当前任务
                    AddLog($"[{id}] end");
                }, cts.Token);
                try
                {
                    //task.Wait(); //无异常。异步任务正常执行结束。
                    task.Wait(cts.Token); //有异常。Token中途取消。异步任务正常执行结束。
                }
                catch (Exception ex)
                {
                    AddLog($"[{id}] {ex.Message}");
                }
            }
        }

        private void RunTaskAndWait(int id, CancellationToken token)
        {
            try
            {
                AddLog($"[{id}] Run task. token.IsCancellationRequested = {token.IsCancellationRequested}");
                var task = RunTask(id, token);
                task.Wait(); // 调用Task.Wait()时，异常传递到当前线程，否则，无异常。
                AddLog($"[{id}] Run task and wait finially.");
            }
            catch (OperationCanceledException oce)
            {
                AddLog($"[{id}] OperationCanceledException: {oce.Message}");
            }
            catch (AggregateException ae)
            {
                foreach (var item in ae.InnerExceptions)
                {
                    AddLog($"[{id}] AggregateException: {item.Message}");
                }
            }
            catch (Exception ex)
            {
                AddLog($"[{id}] Exception: {ex.Message} \n {ex.StackTrace}");
            }
        }

        private Task RunTask(int id, CancellationToken token)
        {
            return Task.Run(() =>
            {
                AddLog($"[{id}] begin");
                Thread.Sleep(3000);
                AddLog($"[{id}] end");
            }, token);
        }

    }
}
